package com.wux.labs.spring.springbucks.configuration

import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.util.ReflectionUtils
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping
import springfox.documentation.builders.ApiInfoBuilder
import springfox.documentation.builders.PathSelectors
import springfox.documentation.builders.RequestHandlerSelectors
import springfox.documentation.oas.annotations.EnableOpenApi
import springfox.documentation.service.Contact
import springfox.documentation.spi.DocumentationType
import springfox.documentation.spring.web.plugins.Docket
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider
import java.lang.reflect.Field
import java.util.stream.Collectors

@Configuration
@EnableOpenApi
class SwaggerConfiguration {
    @Bean
    fun createRestApi(): Docket {
        return Docket(DocumentationType.OAS_30)
            .apiInfo(
                ApiInfoBuilder()
                    .title("中电金信分布式03期初级班")
                    .description("第一次作业")
                    .contact(Contact("伍鲜", "https://gitee.com/wux-labs/Gientech-Works", "wux_labs@outlook.com"))
                    .version("1.0.0")
                    .build()
            )
            .enable(true)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.wux.labs.spring"))
            .paths(PathSelectors.any())
            .build()
            .pathMapping("/")
    }

    @Bean
    fun springfoxHandlerProviderBeanPostProcessor(): BeanPostProcessor {
        return object : BeanPostProcessor {
            override fun postProcessAfterInitialization(bean: Any, beanName: String): Any {
                if (bean is WebMvcRequestHandlerProvider || bean is WebFluxRequestHandlerProvider) {
                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean))
                }
                return bean
            }

            private fun <T : RequestMappingInfoHandlerMapping> customizeSpringfoxHandlerMappings(mappings: MutableList<T>) {
                val copy = mappings.stream()
                    .filter { mapping: T -> mapping.patternParser == null }
                    .collect(Collectors.toList())
                mappings.clear()
                mappings.addAll(copy)
            }

            private fun getHandlerMappings(bean: Any): MutableList<RequestMappingInfoHandlerMapping> {
                return try {
                    val field: Field = ReflectionUtils.findField(bean.javaClass, "handlerMappings")!!
                    field.isAccessible = true
                    field.get(bean) as MutableList<RequestMappingInfoHandlerMapping>
                } catch (e: IllegalArgumentException) {
                    throw IllegalStateException(e)
                } catch (e: IllegalAccessException) {
                    throw IllegalStateException(e)
                }
            }
        }
    }
}